package com.quartet.modules.home.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.quartet.api.ApiResult;
import com.quartet.modules.alarm.service.TTerminalAlarmInfoService;
import com.quartet.modules.customer.service.TCustomerInfoService;
import com.quartet.modules.home.dto.*;
import com.quartet.modules.order.entity.TOrder;
import com.quartet.modules.order.service.TOrderService;
import com.quartet.modules.platform.dto.TPlatformAlarmTotalDto;
import com.quartet.modules.platform.dto.TTerminalPositionDto;
import com.quartet.modules.service.dao.TServiceClickCountDao;
import com.quartet.modules.service.dto.TServiceClickCountDto;
import com.quartet.modules.service.entity.TServiceInfo;
import com.quartet.modules.service.service.TServiceInfoService;
import com.quartet.modules.stock.entity.TTerminalStock;
import com.quartet.modules.stock.service.TTerminalStockService;
import com.quartet.modules.system.service.DictDetailService;
import com.quartet.modules.system.service.DictDetailServicePs;
import com.quartet.modules.system.service.dto.DictDetailDto;
import com.quartet.modules.terminal.service.TTerminalInfoService;
import com.quartet.modules.vehicle.dao.TTerminalPositionInfoDao;
import com.quartet.modules.vehicle.dto.TTerminalPositionInfoDto;
import com.quartet.modules.vehicle.entity.TTerminalPositionInfo;
import com.quartet.modules.vehicle.service.TTerminalPositionInfoService;
import com.quartet.utils.DateUtil;
import com.quartet.utils.LocaleUtils;
import com.quartet.utils.StringUtils;
import com.quartet.utils.constant.MapServerConstant;
import com.quartet.utils.enums.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 首页信息展示(TOrder)表控制层
 *
 * @author makejava
 * @since 2021-05-04 16:40:24
 */
@RestController
@RequestMapping("/home")
@Slf4j
@Api(tags = "业务：首页信息展示")
public class HomeController {

    DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    final static DateTimeFormatter DF_DAY = DateTimeFormatter.ofPattern("HH");
    final static DateTimeFormatter DF_WEEK_MONTH = DateTimeFormatter.ofPattern("MM-dd");

//    @Autowired
//    Executor myThreadPoolExecutor;
//ExecutorService executorService = Executors.newFixedThreadPool(10);
    /**
     * 服务对象
     */
    @Resource
    private DictDetailService dictDetailService;

    @Resource
    private TCustomerInfoService tCustomerInfoService;

    @Resource
    private DictDetailServicePs dictDetailServicePs;

    @Resource
    private TOrderService tOrderService;

    @Resource
    private TTerminalInfoService tTerminalInfoService;

    @Resource
    private TServiceInfoService tServiceInfoService;

    @Resource
    private TTerminalStockService tTerminalStockService;

    /**
     * 服务对象
     */
    @Resource
    private TTerminalAlarmInfoService tOtherAlarmInfoService;

    /**
     * 服务对象
     */
    @Resource
    private TTerminalPositionInfoService tTerminalPositionInfoService;

    /**
     * 服务对象
     */
    @Resource
    private TTerminalPositionInfoDao tTerminalPositionInfoDao;

    /**
     * 服务对象
     */
    @Resource
    private TServiceClickCountDao tServiceClickCountDao;

    /**
     * 分页查询所有数据
     *
     * @param
     * @return 所有数据
     */
    @ApiOperation("分组查询平台统计数据")
    @PostMapping("/queryApplicationPlatformData")
//    @AuthKeyValidated("statisticalAnalysis")
    public ApiResult<List<ApplicationPlatformResponseDto>> queryApplicationPlatformData() {
        List<DictDetailDto> dictDetailDtoList = dictDetailService.getDictByName("applicationType");
        List<ApplicationPlatformResponseDto> applicationPlatformResponseDtoList = dictDetailDtoList.stream().map(dictDetailDto -> {
            ApplicationPlatformResponseDto applicationPlatformResponseDto = new ApplicationPlatformResponseDto();
            applicationPlatformResponseDto.setApplicationType(dictDetailDto.getValue());
            if (LocaleUtils.getLocale().startsWith(MapServerConstant.EN)) {
                applicationPlatformResponseDto.setApplicationTypeLabel(dictDetailDto.getLabelEn());
            } else {
                applicationPlatformResponseDto.setApplicationTypeLabel(dictDetailDto.getLabel());
            }
            QueryWrapper<TOrder> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(TOrder::getApplicationType, dictDetailDto.getValue()).eq(TOrder::getPaymentStatus, OrderStatusEnum.PAID.getValue());
            List<TOrder> orderList = tOrderService.list(queryWrapper);
            if (CollectionUtils.isEmpty(orderList)) {
                return applicationPlatformResponseDto;
            }
            List<String> customerCodeList = orderList.stream().map(TOrder::getCustomerCode).distinct().collect(Collectors.toList());
            applicationPlatformResponseDto.setCustomerNum(customerCodeList.size());

//            List<TOrder> tOrderList = tOrderService.list(new QueryWrapper<TOrder>().lambda().in(TOrder::getCustomerCode, customerCodeList));
            List<String> orderCodeList = orderList.stream().map(tOrder -> tOrder.getOrderCode()).collect(Collectors.toList());
            QueryWrapper<TTerminalStock> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.lambda().in(TTerminalStock::getOrderCode, orderCodeList);
            int connectedDevicesNum = tTerminalStockService.count(queryWrapper1);
            applicationPlatformResponseDto.setConnectedDevicesTotalNumber(connectedDevicesNum);

//            List<String> orderCodeList = orderList.stream().map(order -> order.getOrderCode()).collect(Collectors.toList());
            if ("VehicleApplicationPlatform".equals(dictDetailDto.getValue())) {
                Integer num = tServiceClickCountDao.queryServiceClickTotalNum();
                applicationPlatformResponseDto.setServiceCallTotalNumber(Objects.isNull(num) ? 0 : num);
            } else {
                applicationPlatformResponseDto.setServiceCallTotalNumber(0);
            }
            return applicationPlatformResponseDto;
        }).collect(Collectors.toList());
        return ApiResult.ok(applicationPlatformResponseDtoList);
    }


    /**
     * 统计平台服务数据
     *
     * @param
     * @return 所有数据
     */
    @ApiOperation("统计平台服务数据")
    @PostMapping("/queryPlatformServiceData")
    @ApiImplicitParams({@ApiImplicitParam(name = "queryType", value = "统计周期 1：天 2：周 3：月")})
//    @AuthKeyValidated("statisticalAnalysis")
    public ApiResult<PlatformServiceResponseDto> queryPlatformServiceData(@RequestParam(value = "queryType", required = false) String queryType) {

        List<TServiceInfo> tServiceInfoList = tServiceInfoService.list();

        Map<String, List<TServiceInfo>> serviceMap = tServiceInfoList.stream().collect(Collectors.groupingBy(TServiceInfo::getServiceType));
//        List<TServiceInfo> serviceInfoList = serviceMap.get("map");

        //地图服务统计
        List<DictDetailDto> detailDtoList = dictDetailService.getDictByName("serviceType");
        Map<String, String> map = detailDtoList.stream().collect(Collectors.toMap(DictDetailDto::getValue, DictDetailDto::getLabel));

        PlatformServiceResponseDto platformServiceResponseDto = new PlatformServiceResponseDto();

        Map<String, Integer> integerMap = Arrays.stream(ServiceCountEnum.values()).collect(Collectors.toMap(ServiceCountEnum::getValue, ServiceCountEnum::getCount));
        //服务接口总数
//        platformServiceResponseDto.setServiceTotalNum(integerMap.values().stream().reduce(Integer::sum).orElse(0));
        int count = tServiceInfoService.count();
        platformServiceResponseDto.setServiceTotalNum(count);
//        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> setCustomizedServices(integerMap, map, platformServiceResponseDto), myThreadPoolExecutor);
//        CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> setGeneralService(integerMap, map, platformServiceResponseDto), myThreadPoolExecutor);
//        CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> setServiceStatus(tServiceInfoList, platformServiceResponseDto), myThreadPoolExecutor);
//        CompletableFuture<Void> future3 = CompletableFuture.runAsync(() -> setServiceInvocation(df, tServiceInfoList, platformServiceResponseDto), myThreadPoolExecutor);
//        CompletableFuture<Void> future4 = CompletableFuture.runAsync(() -> setServiceTop(tServiceInfoList, serviceMap, map, platformServiceResponseDto), myThreadPoolExecutor);

//        CompletableFuture.allOf(future, future1, future2, future3, future4);
//        CompletableFuture.allOf(future1, future2, future3, future4);

//        //定制服务
//        setCustomizedServices(serviceInfoList, map, platformServiceResponseDto);
        //通用服务
        setGeneralService(integerMap, map, platformServiceResponseDto);
        //服务状态统计
        setServiceStatus(tServiceInfoList, platformServiceResponseDto);
        //服务调用次数统计
        setServiceInvocation(DF_WEEK_MONTH, platformServiceResponseDto);
        //TOP数据统计

//        if (StringUtils.isBlank(queryType)) {
//            setServiceTop(tServiceInfoList, serviceMap, map, platformServiceResponseDto);
//        } else {
        LocalDateTime localDateTime = null;
        if (StringUtils.isNotBlank(queryType)) {
            localDateTime = LocalDateTime.now();
            if (QueryTypeEnum.DAY.getValue().equals(queryType)) {
                localDateTime = localDateTime.minusDays(1);
            } else if (QueryTypeEnum.WEEK.getValue().equals(queryType)) {
                localDateTime = localDateTime.minusDays(7);
            } else {
                localDateTime = localDateTime.minusMonths(1);
            }
        }

        List<TServiceClickCountDto> tServiceClickCountDtoList = tServiceClickCountDao.queryServiceClickGroupCount(localDateTime);

        List<ServiceTopResponseDto> serviceTopResponseDtoList = tServiceClickCountDtoList.stream().map(tServiceClickCountDto -> {
            ServiceTopResponseDto serviceTopResponseDto = new ServiceTopResponseDto();
            serviceTopResponseDto.setServiceCode(tServiceClickCountDto.getServiceType());
            serviceTopResponseDto.setServiceName(map.get(tServiceClickCountDto.getServiceType()));
            serviceTopResponseDto.setServiceCallTotal(tServiceClickCountDto.getCount());
            return serviceTopResponseDto;
        }).collect(Collectors.toList());

        platformServiceResponseDto.setServiceTopResponseDto(serviceTopResponseDtoList);
//        List<TServiceInfo> tServiceInfoList1 = tServiceInfoService.list(new QueryWrapper<TServiceInfo>().lambda().ge(TServiceInfo::getCreateTime, localDateTime));
//
//        Map<String, List<TServiceInfo>> serviceMap1 = tServiceInfoList1.stream().collect(Collectors.groupingBy(TServiceInfo::getServiceType));
//        setServiceTop(tServiceInfoList1, serviceMap1, map, platformServiceResponseDto);
//        }
        return ApiResult.ok(platformServiceResponseDto);
    }

    /**
     * TOP数据统计
     *
     * @param tServiceInfoList
     * @param serviceMap
     * @param map
     * @param platformServiceResponseDto
     */
    private void setServiceTop(List<TServiceInfo> tServiceInfoList, Map<String, List<TServiceInfo>> serviceMap, Map<String, String> map, PlatformServiceResponseDto platformServiceResponseDto) {
        Map<String, Integer> map2 = serviceMap.keySet().stream().collect(Collectors.toMap(s -> s, x -> serviceMap.get(x).size()));

        Map<String, Integer> sortedMap2 = map2.entrySet().stream()
                .sorted((o1, o2) -> {
                    if (o1.getValue() < o2.getValue()) {
                        return 1;
                    }
                    return -1;
                })
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        Map.Entry::getValue,
                        (oldVal, newVal) -> oldVal,
                        LinkedHashMap::new));

        List<ServiceTopResponseDto> topResponseDtoList = sortedMap2.keySet().stream().map(s -> {
            ServiceTopResponseDto serviceTopResponseDto = new ServiceTopResponseDto();
            serviceTopResponseDto.setServiceCode(s);
            serviceTopResponseDto.setServiceName(map.get(s));
            serviceTopResponseDto.setServiceCallTotal(sortedMap2.get(s));
            return serviceTopResponseDto;
        }).limit(3).collect(Collectors.toList());
        platformServiceResponseDto.setServiceTopResponseDto(topResponseDtoList);
    }

    /**
     * 服务调用次数统计
     *
     * @param df
     * @param platformServiceResponseDto
     */
    private void setServiceInvocation(DateTimeFormatter df, PlatformServiceResponseDto platformServiceResponseDto) {
        List<String> axis = new ArrayList<>();
        LocalDateTime localDateTime = LocalDateTime.now();
        LocalDateTime startLocalDateTime = localDateTime.minusDays(7);
        LinkedHashMap<String, Integer> map1 = new LinkedHashMap<>(7);

        List<TServiceClickCountDto> tServiceClickCountDtoList = tServiceClickCountDao.queryServiceClickTotalCount(startLocalDateTime);

        //生成最近7天的横坐标
        for (int i = 6; i >= 0; i--) {
            String s = df.format(localDateTime.minusDays(i));
            axis.add(s);
            map1.put(s, 0);
        }
        tServiceClickCountDtoList.forEach(tServiceClickCountDto -> {
            LocalDateTime localDateTime1 = DateUtil.parseLocalDateTimeFormat(tServiceClickCountDto.getTime(), DateUtil.DFY_MD_HOUR);
            Integer integer = map1.get(df.format(localDateTime1));
            if (!Objects.isNull(integer)) {
                map1.put(df.format(localDateTime1), integer == null ? 0 : integer + tServiceClickCountDto.getCount());
            }
        });
        ServiceInvocationResponseDto serviceInvocationResponseDto = new ServiceInvocationResponseDto();
        serviceInvocationResponseDto.setAxis(axis);
        serviceInvocationResponseDto.setValueList(new ArrayList<>(map1.values()));
        platformServiceResponseDto.setServiceInvocationResponseDto(serviceInvocationResponseDto);
    }

    /**
     * 服务状态统计
     *
     * @param tServiceInfoList
     * @param platformServiceResponseDto
     */
    private void setServiceStatus(List<TServiceInfo> tServiceInfoList, PlatformServiceResponseDto platformServiceResponseDto) {
//        long enableCount = tServiceInfoList.stream().filter(tServiceInfo -> ServiceStatusEnum.ENABLE.getValue().equals(String.valueOf(tServiceInfo.getStatus()))).count();
//        long disableCount = tServiceInfoList.stream().filter(tServiceInfo -> ServiceStatusEnum.DISABLE.getValue().equals(String.valueOf(tServiceInfo.getStatus()))).count();
//        AtomicInteger invalidCount = new AtomicInteger();
//        tServiceInfoList.stream().forEach(tServiceInfo -> {
//            QueryWrapper<TOrder> queryWrapper = new QueryWrapper();
//            queryWrapper.lambda().eq(TOrder::getOrderCode, tServiceInfo.getOrderCode());
//            TOrder tOrder = tOrderService.getOne(queryWrapper);
//            if (!ObjectUtils.isEmpty(tOrder) && LocalDateTime.now().isBefore(tOrder.getExpireTime())) {
//                invalidCount.getAndIncrement();
//            }
//        });
        int enableCount = 0;
        int disableCount = 0;
        int invalidCount = 0;
        for (TServiceInfo tServiceInfo : tServiceInfoList) {
            QueryWrapper<TOrder> queryWrapper = new QueryWrapper();
            queryWrapper.lambda().eq(TOrder::getOrderCode, tServiceInfo.getOrderCode());
            TOrder tOrder = tOrderService.getOne(queryWrapper);
            if (!ObjectUtils.isEmpty(tOrder) && LocalDateTime.now().isAfter(tOrder.getExpireTime())) {
                invalidCount++;
                continue;
            }
            if (ServiceStatusEnum.ENABLE.getValue().equals(String.valueOf(tServiceInfo.getStatus()))) {
                enableCount++;
                continue;
            }

            if (ServiceStatusEnum.DISABLE.getValue().equals(String.valueOf(tServiceInfo.getStatus()))) {
                disableCount++;
                continue;
            }

        }
        ServiceStatusResponseDto serviceStatusResponseDto = new ServiceStatusResponseDto();
        serviceStatusResponseDto.setUsingServiceTotal((int) enableCount);
        serviceStatusResponseDto.setStopUsingServiceTotal((int) disableCount);
        serviceStatusResponseDto.setInvalidCount(invalidCount);
        platformServiceResponseDto.setServiceStatusResponseDto(serviceStatusResponseDto);
    }

    /**
     * 通用服务
     *
     * @param integerMap
     * @param map
     * @param platformServiceResponseDto
     */
    private void setGeneralService(Map<String, Integer> integerMap, Map<String, String> map, PlatformServiceResponseDto platformServiceResponseDto) {
//        List<ServiceTotalResponseDto> serviceTotalResponseDtoList = new ArrayList<>();
//        Integer count = integerMap.get("map");
//        ServiceTotalResponseDto serviceTotalResponseDto1 = new ServiceTotalResponseDto();
//        serviceTotalResponseDto1.setServiceCode("map");
//        serviceTotalResponseDto1.setServiceName(map.get("map"));
//        serviceTotalResponseDto1.setServiceTotalNum(count);
//        serviceTotalResponseDtoList.add(serviceTotalResponseDto1);
//        platformServiceResponseDto.setGeneralServices(serviceTotalResponseDtoList);
        List<ServiceTotalResponseDto> serviceTotalResponseDtoList = new ArrayList<>();
        integerMap.keySet().stream().forEach(x -> {
            QueryWrapper<TServiceInfo> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.lambda().in(TServiceInfo::getServiceType, x);
            int count = tServiceInfoService.count(queryWrapper1);
            ServiceTotalResponseDto serviceTotalResponseDto = new ServiceTotalResponseDto();
            serviceTotalResponseDto.setServiceCode(x);
            serviceTotalResponseDto.setServiceName(map.get(x));
            serviceTotalResponseDto.setServiceTotalNum(count);
            serviceTotalResponseDtoList.add(serviceTotalResponseDto);
        });
        platformServiceResponseDto.setGeneralServices(serviceTotalResponseDtoList);

    }

    /**
     * 定制服务
     *
     * @param integerMap
     * @param map
     * @param platformServiceResponseDto
     */
//    private void setCustomizedServices(Map<String, Integer> integerMap, Map<String, String> map, PlatformServiceResponseDto platformServiceResponseDto) {
//        integerMap.keySet().stream().filter(s -> !"map".equals(s)).forEach(x -> {
//            List<ServiceTotalResponseDto> serviceTotalResponseDtoList = new ArrayList<>();
//            ServiceTotalResponseDto serviceTotalResponseDto = new ServiceTotalResponseDto();
//            serviceTotalResponseDto.setServiceCode(x);
//            serviceTotalResponseDto.setServiceName(map.get(x));
//            serviceTotalResponseDtoList.add(serviceTotalResponseDto);
//            platformServiceResponseDto.setCustomizedServices(serviceTotalResponseDtoList);
//        });
//    }


    /**
     * 统计接入终端设备
     *
     * @param
     * @return 所有数据
     */
    @ApiOperation("统计接入终端设备")
    @PostMapping("/queryAccessTerminalEquipment")
//    @AuthKeyValidated("statisticalAnalysis")
    public ApiResult<AccessTerminalEquipmentResponseDto> queryAccessTerminalEquipment() {
        List<DictDetailDto> detailDtoList = dictDetailService.getDictByName("applicationType");
        List<String> axis = new ArrayList<>(7);
        List<Integer> valueList = new ArrayList<>(7);
        detailDtoList.forEach(dictDetailDto -> {
            List<TOrder> tOrderList = tOrderService.list(new QueryWrapper<TOrder>().lambda().eq(TOrder::getApplicationType, dictDetailDto.getValue()));
            Integer count = tOrderList.stream().collect(Collectors.summingInt(TOrder::getQuantity));
            axis.add(dictDetailDto.getLabel());
            valueList.add(count);
        });
        AccessTerminalEquipmentResponseDto accessTerminalEquipmentResponseDto = new AccessTerminalEquipmentResponseDto();
        accessTerminalEquipmentResponseDto.setAxis(axis);
        accessTerminalEquipmentResponseDto.setValueList(valueList);
        return ApiResult.ok(accessTerminalEquipmentResponseDto);
    }

    /**
     * 统计终端状态
     *
     * @param
     * @return 所有数据
     */
    @ApiOperation("统计终端状态")
    @PostMapping("/queryTerminalStatus")
//    @AuthKeyValidated("statisticalAnalysis")
    public ApiResult<TerminalStatusResponseDto> queryTerminalStatus() {
        List<TTerminalStock> tTerminalStockList = tTerminalStockService.list();
        long allocatedCount = tTerminalStockList.stream().filter(tTerminalStock -> InventoryStatusEnum.ALLOCATED.getValue().equals(tTerminalStock.getInventoryStatus())).count();
        long unallocatedCount = tTerminalStockList.stream().filter(tTerminalStock -> InventoryStatusEnum.UNALLOCATED.getValue().equals(tTerminalStock.getInventoryStatus())).count();
        long toBeAllocatedTerminalsNum = tTerminalStockList.stream().filter(tTerminalStock -> InventoryStatusEnum.TOBEALLOCATED.getValue().equals(tTerminalStock.getInventoryStatus())).count();
        TerminalStatusResponseDto terminalStatusResponseDto = new TerminalStatusResponseDto();
        terminalStatusResponseDto.setAssignedTerminalsNum(allocatedCount);
        terminalStatusResponseDto.setUnallocatedTerminalsNum(unallocatedCount);
        terminalStatusResponseDto.setToBeAllocatedTerminalsNum(toBeAllocatedTerminalsNum);
        return ApiResult.ok(terminalStatusResponseDto);
    }

    /**
     * 统计实时调用数据-折线图
     *
     * @param
     * @return 所有数据
     */
    @ApiOperation("统计实时调用数据-折线图")
    @PostMapping("/queryApplicationAccessDataBrokenLine")
//    @AuthKeyValidated("statisticalAnalysis")
    public ApiResult<List<ApplicationAccessResponseDto>> queryApplicationAccessDataBrokenLine() {
        List<ApplicationAccessResponseDto> applicationAccessResponseDtoList = new ArrayList<>();
        DateTimeFormatter df = DateTimeFormatter.ofPattern("HH");
//        List<String> axis = new ArrayList<>();
        LocalDateTime localDateTime = LocalDateTime.now();
        LocalDateTime startLocalDateTime = localDateTime.minusDays(1);
//        LinkedHashMap<String, Integer> map1 = new LinkedHashMap<>(24);
//        //生成最近7天的横坐标
//        for (int i = 23; i >= 0; i--) {
//            String s = df.format(localDateTime.minusHours(i));
//            axis.add(s);
//            map1.put(s, 0);
//        }
        List<DictDetailDto> detailDtoList = dictDetailService.getDictByName("applicationType");
        List<Integer> valueList = new ArrayList<>(7);
        detailDtoList.forEach(dictDetailDto -> {
            List<String> axis = new ArrayList<>();
            LinkedHashMap<String, Integer> map1 = new LinkedHashMap<>(24);
            //生成最近7天的横坐标
            for (int i = 23; i >= 0; i--) {
                String s = df.format(localDateTime.minusHours(i));
                axis.add(s);
                map1.put(s, 0);
            }
            List<TOrder> tOrderList = tOrderService.list(new QueryWrapper<TOrder>().lambda().eq(TOrder::getApplicationType, dictDetailDto.getValue()));
            for (TOrder tOrder : tOrderList) {
                QueryWrapper<TTerminalStock> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().eq(TTerminalStock::getOrderCode, tOrder.getOrderCode());
                List<TTerminalStock> tTerminalStockList = tTerminalStockService.list(queryWrapper);

                if (CollectionUtils.isEmpty(tTerminalStockList)) {
                    continue;
                }
                List<String> terminalCodeList = tTerminalStockList.stream().map(TTerminalStock::getTerminalCode).collect(Collectors.toList());
                List<TTerminalPositionInfo> tTerminalPositionInfoList = tTerminalPositionInfoService.list(
                        new QueryWrapper<TTerminalPositionInfo>().lambda()
                                .in(TTerminalPositionInfo::getTerminalCode, terminalCodeList)
                                .gt(TTerminalPositionInfo::getCreateTime, startLocalDateTime)
                                .lt(TTerminalPositionInfo::getCreateTime, localDateTime)
                                .orderByDesc(TTerminalPositionInfo::getCreateTime)
                );

                tTerminalPositionInfoList.forEach(tTerminalPositionInfo -> {
                    Integer integer = map1.get(df.format(tTerminalPositionInfo.getCreateTime()));
                    if (!Objects.isNull(integer)) {
                        map1.put(df.format(tTerminalPositionInfo.getCreateTime()), integer + 1);
                    }
                });
            }
            ApplicationAccessResponseDto applicationAccessResponseDto = new ApplicationAccessResponseDto();
            applicationAccessResponseDto.setApplicationName(dictDetailDto.getLabel());
            applicationAccessResponseDto.setAxis(axis);
            applicationAccessResponseDto.setValueList(new ArrayList<>(map1.values()));
            applicationAccessResponseDtoList.add(applicationAccessResponseDto);
        });
        return ApiResult.ok(applicationAccessResponseDtoList);
    }

    /**
     * 统计实时调用数据-柱状图
     *
     * @param
     * @return 所有数据
     */
    @ApiOperation("统计实时调用数据-柱状图")
    @PostMapping("/queryApplicationAccessDataColumnar")
//    @AuthKeyValidated("statisticalAnalysis")
    public ApiResult<AccessServiceCallResponseDto> queryApplicationAccessDataColumnar() {
        List<DictDetailDto> detailDtoList = dictDetailService.getDictByName("applicationType");
        List<String> axis = new ArrayList<>(7);
        List<Integer> valueList = new ArrayList<>(7);
        detailDtoList.forEach(dictDetailDto -> {
            List<TOrder> tOrderList = tOrderService.list(new QueryWrapper<TOrder>().lambda().eq(TOrder::getApplicationType, dictDetailDto.getValue()));
            int total = 0;
            for (TOrder tOrder : tOrderList) {
                QueryWrapper<TServiceInfo> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().eq(TServiceInfo::getOrderCode, tOrder.getOrderCode());
                int sum = tServiceInfoService.list(queryWrapper).stream().mapToInt(TServiceInfo::getServiceClickCount).sum();
                total = total + sum;
            }
            axis.add(dictDetailDto.getLabel());
            valueList.add(total);
        });
        AccessServiceCallResponseDto accessServiceCallResponseDto = new AccessServiceCallResponseDto();
        accessServiceCallResponseDto.setAxis(axis);
        accessServiceCallResponseDto.setValueList(valueList);
        return ApiResult.ok(accessServiceCallResponseDto);
    }

    /**
     * 统计新增数量按日周月
     *
     * @param
     * @return 所有数据
     */
    @ApiOperation("统计新增数量按日周月")
    @PostMapping("/queryAddCallCountByDayWeekMonth")
    @ApiImplicitParams({@ApiImplicitParam(name = "queryType", value = "统计周期 1：天 2：周 3：月")})
//    @AuthKeyValidated("statisticalAnalysis")
    public ApiResult<ApplicationAccessResponseDto> queryAddCallCountByDayWeekMonth(@RequestParam("queryType") String queryType) {
        LocalDateTime localDateTime = LocalDateTime.now();
        LinkedHashMap<String, Integer> map1 = new LinkedHashMap<>(24);
        //生成X轴坐标名
        List<String> axis = new ArrayList<>();
        LocalDateTime startTime;
        if (QueryTypeEnum.DAY.getValue().equals(queryType)) {
            for (int i = 23; i >= 0; i--) {
                String s = DF_DAY.format(localDateTime.minusHours(i));
                axis.add(s);
                map1.put(s, 0);
            }
            startTime = localDateTime.minusHours(24);
        } else if (QueryTypeEnum.WEEK.getValue().equals(queryType)) {
            for (int i = 6; i >= 0; i--) {
                String s = DF_WEEK_MONTH.format(localDateTime.minusDays(i));
                axis.add(s);
                map1.put(s, 0);
            }
            startTime = localDateTime.minusDays(6).withHour(0).withMinute(0).withSecond(0);
        } else {
            for (int i = 29; i >= 0; i--) {
                String s = DF_WEEK_MONTH.format(localDateTime.minusDays(i));
                axis.add(s);
                map1.put(s, 0);
            }
            startTime = localDateTime.minusDays(29).withHour(0).withMinute(0).withSecond(0);
        }
//        QueryWrapper<TServiceInfo> queryWrapper = new QueryWrapper<>();
//        queryWrapper.lambda().ge(TServiceInfo::getCreateTime, startTime);
//        List<TServiceInfo> tServiceInfoList = tServiceInfoService.list(queryWrapper);
        List<TTerminalPositionInfoDto> tTerminalPositionInfoDtoList;
        if (QueryTypeEnum.DAY.getValue().equals(queryType)) {
            tTerminalPositionInfoDtoList = tTerminalPositionInfoDao.queryPositionInfoByHour(startTime);
        } else {
            tTerminalPositionInfoDtoList = tTerminalPositionInfoDao.queryPositionInfoByDay(startTime);
        }

        tTerminalPositionInfoDtoList.forEach(tTerminalPositionInfoDto -> {
            Integer integer;
            if (QueryTypeEnum.DAY.getValue().equals(queryType)) {
                integer = map1.get(tTerminalPositionInfoDto.getCreateTime());
                if (!Objects.isNull(integer)) {
                    map1.put(tTerminalPositionInfoDto.getCreateTime(), integer == null ? 0 : integer + tTerminalPositionInfoDto.getCount());
                }
            } else {
                integer = map1.get(tTerminalPositionInfoDto.getCreateTime());
                if (!Objects.isNull(integer)) {
                    map1.put(tTerminalPositionInfoDto.getCreateTime(), integer == null ? 0 : integer + tTerminalPositionInfoDto.getCount());
                }
            }

        });
        ApplicationAccessResponseDto applicationAccessResponseDto = new ApplicationAccessResponseDto();
        applicationAccessResponseDto.setAxis(axis);
        applicationAccessResponseDto.setValueList(new ArrayList<>(map1.values()));
        return ApiResult.ok(applicationAccessResponseDto);
    }

    /**
     * 统计设备总数
     *
     * @param
     * @return 所有数据
     */
    @ApiOperation("统计设备总数")
    @PostMapping("/queryTerminalTotal")
//    @AuthKeyValidated("statisticalAnalysis")
    public ApiResult<Integer> queryTerminalTotal() {
        int count = tTerminalInfoService.count();
        return ApiResult.ok(count);
    }

    /**
     * 设备在线实时数据
     *
     * @param
     * @return 所有数据
     */
    @ApiOperation("设备在线实时数据")
    @PostMapping("/queryTerminalOnLineData")
//    @AuthKeyValidated("statisticalAnalysis")
    @ApiImplicitParams({@ApiImplicitParam(name = "applicationType", value = "应用类型\n" +
            "     * VehicleApplicationPlatform：车辆应用\n" +
            "     * shipApplicationPlatform：船舶应用\n" +
            "     * precisionAgricultureApplicationPlatform：精准农业应用\n" +
            "     * uavApplicationPlatform：无人机应用\n" +
            "     * publicSecurityApplicationPlatform：公共安全应用\n" +
            "     * digitalConstructionApplicationPlatform：数字施工应用")})
    public ApiResult<TerminalOnLineDataResponseDto> queryTerminalOnLineData(@RequestParam(value = "applicationType", required = false) String applicationType) {
        List<TOrder> tOrderList;
        if (StringUtils.isNotBlank(applicationType)) {
            tOrderList = tOrderService.list(new QueryWrapper<TOrder>().lambda().eq(TOrder::getApplicationType, applicationType));
        } else {
            tOrderList = tOrderService.list(new QueryWrapper<TOrder>().lambda().eq(TOrder::getApplicationType, "VehicleApplicationPlatform"));
        }
        List<String> orderCodeList = tOrderList.stream().filter(tOrder -> tOrder.getExpireTime().isAfter(LocalDateTime.now())).map(tOrder -> tOrder.getOrderCode()).collect(Collectors.toList());
        //1、在线车辆（车辆应用的在线终端）
        QueryWrapper<TTerminalStock> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().in(TTerminalStock::getOrderCode, orderCodeList);
        List<String> tTerminalCodeList = tTerminalStockService.list(queryWrapper).stream().map(TTerminalStock::getTerminalCode).collect(Collectors.toList());

        TerminalOnLineDataResponseDto terminalOnLineDataResponseDto = new TerminalOnLineDataResponseDto();
        //1、车辆总里程数top10

        TTerminalPositionDto tTerminalPositionDto = new TTerminalPositionDto();
        List<TTerminalPositionDto> tTerminalPositionDtoList = tTerminalPositionInfoService.queryTerminalMileageTop(tTerminalCodeList);
        terminalOnLineDataResponseDto.setTTerminalPositionDtoList(tTerminalPositionDtoList);
        //2、车辆在线率
        TerminalOnLineStatusResponseDto terminalOnLineStatusResponseDto = tTerminalPositionInfoService.queryTerminalOnLineRate(tTerminalCodeList);
        terminalOnLineDataResponseDto.setTerminalOnLineStatusResponseDto(terminalOnLineStatusResponseDto);
        //3、车辆实时数据
        ApplicationAccessResponseDto applicationAccessResponseDto = getTerminalOnLineDataResponseDtoApiResult();
        terminalOnLineDataResponseDto.setApplicationAccessResponseDto(applicationAccessResponseDto);
        //4、报警类型统计
        List<TPlatformAlarmTotalDto> alarmInfoLastWeek = tTerminalPositionInfoService.getAlarmTotalCountLastWeek();
        terminalOnLineDataResponseDto.setTPlatformAlarmTotalDtoList(alarmInfoLastWeek);
        //5、过去一周新增报警数据
        Map<String, Double> addAlarmMap = tTerminalPositionInfoService.queryTerminalAlarmLastWeek();
        terminalOnLineDataResponseDto.setAddAlarmMap(addAlarmMap);
        //6、过去一周新增位置数据
        Map<String, Double> addPositionMap = tTerminalPositionInfoService.queryTerminalPositionLastWeek();
        terminalOnLineDataResponseDto.setAddPositionMap(addPositionMap);
        //7、终端实时位置信息
        List<TTerminalCurrentPositionResponseDto> tTerminalCurrentPositionResponseDtoList = tTerminalPositionInfoService.queryTerminalCurrentPosition(tTerminalCodeList);
        terminalOnLineDataResponseDto.setTTerminalCurrentPositionResponseDtoList(tTerminalCurrentPositionResponseDtoList);
        return ApiResult.ok(terminalOnLineDataResponseDto);
    }

    /**
     * 功能描述: 获取车辆实时数据
     *
     * @param
     * @return com.quartet.api.ApiResult<com.quartet.modules.home.dto.TerminalOnLineDataResponseDto>
     * @author huipanxing huipanxing@chinasofti.com
     * @date 2021/7/5 14:19
     */
    private ApplicationAccessResponseDto getTerminalOnLineDataResponseDtoApiResult() {
        DateTimeFormatter df = DateTimeFormatter.ofPattern("HH");
        List<String> axis = new ArrayList<>();
        LocalDateTime localDateTime = LocalDateTime.now();
        LocalDateTime startLocalDateTime = localDateTime.minusDays(1);
        LinkedHashMap<String, Integer> map1 = new LinkedHashMap<>(24);
        //生成最近7天的横坐标
        for (int i = 23; i >= 0; i--) {
            String s = df.format(localDateTime.minusHours(i));
            axis.add(s);
            map1.put(s, 0);
        }
        List<TOrder> tOrderList = tOrderService.list(new QueryWrapper<TOrder>().lambda().eq(TOrder::getApplicationType, "VehicleApplicationPlatform"));
        for (TOrder tOrder : tOrderList) {
            QueryWrapper<TTerminalStock> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(TTerminalStock::getOrderCode, tOrder.getOrderCode());
            List<TTerminalStock> tTerminalStockList = tTerminalStockService.list(queryWrapper);

            if (CollectionUtils.isEmpty(tTerminalStockList)) {
                continue;
            }
            List<String> terminalCodeList = tTerminalStockList.stream().map(TTerminalStock::getTerminalCode).collect(Collectors.toList());
            List<TTerminalPositionInfo> tTerminalPositionInfoList = tTerminalPositionInfoService.list(
                    new QueryWrapper<TTerminalPositionInfo>().lambda()
                            .in(TTerminalPositionInfo::getTerminalCode, terminalCodeList)
                            .gt(TTerminalPositionInfo::getCreateTime, startLocalDateTime)
                            .lt(TTerminalPositionInfo::getCreateTime, localDateTime)
                            .orderByDesc(TTerminalPositionInfo::getCreateTime)
            );

            tTerminalPositionInfoList.forEach(tTerminalPositionInfo -> {
                Integer integer = map1.get(df.format(tTerminalPositionInfo.getCreateTime()));
                if (!Objects.isNull(integer)) {
                    map1.put(df.format(tTerminalPositionInfo.getCreateTime()), integer + 1);
                }
            });
        }
        ApplicationAccessResponseDto applicationAccessResponseDto = new ApplicationAccessResponseDto();
        applicationAccessResponseDto.setApplicationName(dictDetailServicePs.getLabelByValueByCodeAndName("VehicleApplicationPlatform", "applicationType"));
        applicationAccessResponseDto.setAxis(axis);
        applicationAccessResponseDto.setValueList(new ArrayList<>(map1.values()));
        return applicationAccessResponseDto;
    }


}
